package edu.gatech.cs2340.teamrocket.control;

import java.util.ArrayList;
import java.util.List;

/**
 * This class represents a weighted random choice. That is, not all choices
 * have an equal chance of selection. Some choices are more probable than
 * others.
 *
 * @author Joe Tacheron
 */
public class WeightedRandom<T> {

    private class WeightedChoice<T> {
        T data;
        int weight;

        WeightedChoice(T choice, int weight){
            this.data = choice;
            this.weight = weight;
        }
    }

    private int total;
    private List<WeightedChoice<T>> choices;

    /**
     * Simple constructor with no choices.
     */
    public WeightedRandom(){
        choices = new ArrayList<WeightedChoice<T>>();
    }

    /**
     * Add a choice. Weight can be any positive int. Weight is only relevant
     * when there is at least two choices. Weight has no intrinsic value; It's
     * value is relative to other choice's weight. For example, two choices with
     * weights 100 and 100 is equivalent to two choices with weights 1 and 1.
     *
     * @param data The choice
     * @param weight The relative probability this choice should be selected.
     */
    public void addChoice(T data, int weight){
        if(weight <= 0)
            throw new IllegalArgumentException("weight must be positive");

        total += weight;
        choices.add(new WeightedChoice<T>(data, weight));
    }

    /**
     * Select a random choice.
     *
     * @return a random choice
     */
    public T nextChoice(){
        int randomChoice = (int)(Math.random() * total);
        for(WeightedChoice<T> choice : choices){
            if(randomChoice < choice.weight)
                return choice.data;
            randomChoice -= choice.weight;
        }
        throw new RuntimeException("WeightedRandom did not choose anything");
    }
}
